/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package GPSTracker;


import javax.microedition.location.*;
import javax.microedition.io.file.*;
import java.io.*;
import javax.microedition.io.*;
import sUtils.*;


/**
 *
 * @author thomas.s
 */
public class GPSTrackerThread extends Object implements LocationListener {
    private static final String[] courseList =
        {"N", "NNO", "NO", "NOO", "O", "SOO", "SO", "SSO", "S", "SSW", "SW", "SWW", "W", "NWW", "NW", "NNW"};
    LocationProvider locationProvider;
    QualifiedCoordinates lastCoord;
    FileConnection fGPX;
    DataOutputStream sGPX;
    public double lon, lat, alt, old_lon, old_lat, old_alt, course, speed, dist, speedmax, speedn, speeds, time, altsum, altold;
    public long lastLog, lastUpdate, myUpdate, lastTime, lastAlt, old_time=0, old_timesaved=0, curr_time=0;
    public boolean exit;
    String courseText;
    String trackName;
    public boolean trackrecord;
    
    GPSTrackerThread()
    {
        old_lon = old_lat = old_alt = course = lon = lat = alt = speed = speedmax = dist = speeds = time = 0;
        speedn = 1;
        altsum=0; altold=-1;
        exit = false;
        myUpdate = lastUpdate = lastTime = lastAlt = 0;
        locationProvider = null;
        lastCoord = null;
        trackrecord = false;
        courseText = "";
        trackName = "";
        sGPX=null;
        fGPX=null;

        //dist = 12345.80;
    }

    public void reset()
    {
        old_lon = old_lat = old_alt = dist = speed = speedmax = speeds = 0; speedn = 1;
        time = lastTime = lastAlt = old_time = old_timesaved = curr_time = 0;
        altsum = 0; altold = -1;
    }

    public void record()
    {
        trackrecord = true;
    }
    
    public void stop()
    {
        trackrecord=false;
        try { Thread.sleep(100); } catch(Exception e) {}
        closeGPX();
    }
    
    public boolean recording() { return trackrecord; }

    public void writeGPX( String s ) {
        try {
        if (sGPX!=null) {
            sGPX.write(s.getBytes(),0,s.length());
        } } catch( IOException e ) { }
    }

    public boolean openGPX()
    {
            closeGPX();
            trackName = "Tour-"+Strings.getDateID()+"-"+Strings.getTimeID();

            try{
                fGPX = (FileConnection) Connector.open("file:///mmc/" + trackName +".gpx");
                if (fGPX.exists()) fGPX.delete();
                fGPX.create();
            } catch( Exception e ) { fGPX=null; }
            
            if (fGPX==null)
            {
               try {
                    fGPX = (FileConnection) Connector.open("file:///record/" + trackName +".gpx");
                    if (fGPX.exists()) fGPX.delete();
                    fGPX.create();
                } catch( Exception e ) { fGPX=null; }
            }
            if (fGPX==null) return false;

            try { sGPX = fGPX.openDataOutputStream(); } catch(Exception e) { sGPX=null; }
            if (sGPX==null) return false;

            writeGPX("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n<gpx>\r\n");
            writeGPX(" <trk>\r\n <name>" + trackName +"</name>\r\n  <trkseg>\r\n");
            return sGPX!=null;
    }

    private void saveGPXData( double LAT, double LON, double ALT, long TIME )
    {
        StringBuffer sb = new StringBuffer(50);
        sb.append("   <trkpt lat=\""); sb.append(LAT); sb.append("\" lon=\""); sb.append(LON); sb.append("\">");
        sb.append(" <ele>"); sb.append(((int)ALT)); sb.append("</ele>");
        sb.append(" <time>"); sb.append(Strings.getTZ(TIME)); sb.append("</time>");
        sb.append("</trkpt>\r\n");
        writeGPX(sb.toString()); 
    }

    public void logGPXData()
    {
        if (trackrecord)
        {
            if (sGPX==null) openGPX();
            if ( old_lon!=lon || old_lat!=lat || old_alt!=alt )
            {
                if ( old_time>old_timesaved ) saveGPXData( old_lat, old_lon, old_alt, old_time );
                saveGPXData( lat, lon, alt, curr_time );
                old_timesaved = curr_time;
                old_lon = lon;
                old_lat = lat;
                old_alt = alt;
            }
            old_time = curr_time;
        }
   }

    public void closeGPX()
    {
        if (sGPX!=null)
        {
            writeGPX("  </trkseg>\r\n </trk>\r\n");
            writeGPX("</gpx>\r\n");
            try {
                sGPX.close();
                fGPX.close();
            } catch( IOException e ) {}
            sGPX=null;
            fGPX=null;
        }
    }

    public boolean createLocator()
    {
        Criteria crit = new Criteria ();
        crit.setPreferredResponseTime(Criteria.NO_REQUIREMENT);
        crit.setPreferredPowerConsumption(Criteria.NO_REQUIREMENT);
        crit.setHorizontalAccuracy(100);
        crit.setVerticalAccuracy(100);
        crit.setSpeedAndCourseRequired(true);
        //crit.setCostAllowed(false);

        try {
            locationProvider = LocationProvider.getInstance(crit);
            locationProvider.setLocationListener(this, 1, 1, 1);
        }
        catch (LocationException le) {
            locationProvider = null;
        }
        
       // openGPXTrack();
        return locationProvider!=null;

    }

    public boolean updateLocator()
    {
        if (locationProvider==null || lastUpdate<=myUpdate) return false; // nix neues
        myUpdate=lastUpdate;
        logGPXData();
        return true;
    }

    public boolean locatorOk() {
        if (locationProvider==null) return false;
        return locationProvider.getState()==LocationProvider.AVAILABLE;
    }


    public void locationUpdated( LocationProvider p, final Location loc ) {
        QualifiedCoordinates c = loc.getQualifiedCoordinates();
        lon = c.getLongitude();
        lat = c.getLatitude();
        alt = c.getAltitude(); if (alt==0) alt = old_alt;
        speed = loc.getSpeed();
        course = loc.getCourse();
        curr_time = System.currentTimeMillis();

        courseText = courseList[(int)((course+360.0)/(360.0/16.0)+0.5)%16];
        double dd = lastCoord!=null ? lastCoord.distance(c) : 0;

        if (lastTime>0) time += curr_time-lastTime;
        if (speed>0.1)
        {
            dist += dd;
            if (speed>speedmax) speedmax = speed;
            speeds+=speed; speedn+=1;
            lastTime = curr_time;
        }
        else
            lastTime = 0;

        if ( (curr_time-lastAlt)>20000 )
        {
            if (lastAlt>0 && altold<alt) altsum += alt-altold;
            altold = alt;
            lastAlt = curr_time;
        }
        lastCoord = c;
        lastUpdate = curr_time;

    }

    public void providerStateChanged( LocationProvider p, final int _state ) {
     //   if (p.getState()!=LocationProvider.AVAILABLE) lastUpdate=0;
    }

    
}
